R Schnittstellen - Interaktive Darstellung mit Javascript und R

Jan-Philipp Kolb

8 Mai 2017

Interaktive Karten mit dem Javascript Paket leaflet

Die Daten - Weltkulturerbe

url <- "https://raw.githubusercontent.com/Japhilko/
GeoData/master/2015/data/whcSites.csv"

whcSites <- read.csv(url) 
whcSitesDat <- with(whcSites,data.frame(name_en,
                                        category))
library(knitr)
kable(head(whcSitesDat))
name_en category
Cultural Landscape and Archaeological Remains of the Bamiyan Valley Cultural
Minaret and Archaeological Remains of Jam Cultural
Historic Centres of Berat and Gjirokastra Cultural
Butrint Cultural
Al Qal’a of Beni Hammad Cultural
M’Zab Valley Cultural

Das Paket DT

install.packages("DT")

Weitere Variablen WHC Datensatz

whcSitesDat2 <- with(whcSites,data.frame(name_en,category,longitude,latitude,date_inscribed,area_hectares,danger_list))
library('DT')
datatable(whcSitesDat2)

Das Ergebnis bei Rpubs

http://rpubs.com/Japhilko82/WHCdata

Das Paket magrittr

install.packages("magrittr")
library("magrittr")

Die Pipes nutzen

library(magrittr)

str1 <- "Hallo Welt"
str1 %>% substr(1,5)
## [1] "Hallo"
str1 %>% substr(1,5) %>% toupper()
## [1] "HALLO"

Das Paket leaflet

install.packages("leaflet")
library("leaflet")

Eine interaktive Karte erstellen

m <- leaflet() %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(lng=whcSites$lon, 
             lat=whcSites$lat, 
             popup=whcSites$name_en)
m

Die Karte zeigen

Farbe hinzu

whcSites$color <- "red"
whcSites$color[whcSites$category=="Cultural"] <- "blue"
whcSites$color[whcSites$category=="Mixed"] <- "orange"

Eine Karte mit Farbe erzeugen

m1 <- leaflet() %>%
  addTiles() %>%  
  addCircles(lng=whcSites$lon, 
             lat=whcSites$lat, 
             popup=whcSites$name_en,
             color=whcSites$color)

Die Karte mit mehr Farbe

Weltkulturerbe

Weltkulturerbe

Die Karte abspeichern

Layers ein- und ausblenden

m2 <- leaflet() %>%
  addTiles(group = "OSM (default)") %>%  
  addProviderTiles("Stamen.Toner", group = "Toner") %>%
  addProviderTiles("Stamen.TonerLite", group = "Toner Lite") %>%

  addCircles(lng=whcSites$lon, 
             lat=whcSites$lat, 
             popup=whcSites$name_en) %>% 
  
  addLayersControl(
    baseGroups = c("OSM (default)", "Toner", "Toner Lite"),
    options = layersControlOptions(collapsed = FALSE)
  )
m2

Ein weiteres Beispiel mit Erdbebendaten

outline <- quakes[chull(quakes$long, quakes$lat),]
map <- leaflet(quakes) %>%
  # Base groups
  addTiles(group = "OSM (default)") %>%
  addProviderTiles("Stamen.Toner", group = "Toner") %>%
  addProviderTiles("Stamen.TonerLite", group = "Toner Lite") %>%
  # Overlay groups
  addCircles(~long, ~lat, ~10^mag/5, stroke = F, group = "Quakes") %>%
  addPolygons(data = outline, lng = ~long, lat = ~lat,
    fill = F, weight = 2, color = "#FFFFCC", group = "Outline") %>%
  # Layers control
  addLayersControl(
    baseGroups = c("OSM (default)", "Toner", "Toner Lite"),
    overlayGroups = c("Quakes", "Outline"),
    options = layersControlOptions(collapsed = FALSE)
  )
map

Karte mit Polygonen erzeugen

library(sp)
Sr1 = Polygon(cbind(c(2, 4, 4, 1, 2), c(2, 3, 5, 4, 2)))
Sr2 = Polygon(cbind(c(5, 4, 2, 5), c(2, 3, 2, 2)))
Sr3 = Polygon(cbind(c(4, 4, 5, 10, 4), c(5, 3, 2, 5, 5)))
Sr4 = Polygon(cbind(c(5, 6, 6, 5, 5), c(4, 4, 3, 3, 4)), hole = TRUE)
Srs1 = Polygons(list(Sr1), "s1")
Srs2 = Polygons(list(Sr2), "s2")
Srs3 = Polygons(list(Sr4, Sr3), "s3/4")
SpP = SpatialPolygons(list(Srs1, Srs2, Srs3), 1:3)
leaflet(height = "300px") %>% addPolygons(data = SpP)

Beispiel US Staaten

library(maps)
mapStates = map("state", fill = TRUE, plot = FALSE)
leaflet(data = mapStates) %>% addTiles() %>%
  addPolygons(fillColor = topo.colors(10, alpha = NULL), stroke = FALSE)

Die Basiskarte ändern

m <- leaflet() %>% setView(lng = -71.0589, lat = 42.3601, zoom = 12)
m %>% addTiles()
m %>% addProviderTiles("Stamen.Toner")

Basiskarte - CartoDB

m %>% addProviderTiles("CartoDB.Positron")

Esri.NatGeoWorldMap

m %>% addProviderTiles("Esri.NatGeoWorldMap")

OpenTopoMap

m %>% addProviderTiles("OpenTopoMap")

Thunderforest.OpenCycleMap

m %>% addProviderTiles("Thunderforest.OpenCycleMap")

WMS Tiles hinzufügen

leaflet() %>% addTiles() %>% setView(-93.65, 42.0285, zoom = 4) %>%
  addWMSTiles(
    "http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi",
    layers = "nexrad-n0r-900913",
    options = WMSTileOptions(format = "image/png", transparent = TRUE),
    attribution = "Weather data © 2012 IEM Nexrad"
  )

Mehrere Layer miteinander kombinieren

m %>% addProviderTiles("MtbMap") %>%
  addProviderTiles("Stamen.TonerLines",
    options = providerTileOptions(opacity = 0.35)) %>%
  addProviderTiles("Stamen.TonerLabels")

Andere Marker benutzen

greenLeafIcon <- makeIcon(
  iconUrl = "http://leafletjs.com/examples/custom-icons/leaf-green.png",
  iconWidth = 38, iconHeight = 95,
  iconAnchorX = 22, iconAnchorY = 94,
  shadowUrl = "http://leafletjs.com/examples/custom-icons/leaf-shadow.png",
  shadowWidth = 50, shadowHeight = 64,
  shadowAnchorX = 4, shadowAnchorY = 62
)

leaflet(data = quakes[1:4,]) %>% addTiles() %>%
  addMarkers(~long, ~lat, icon = greenLeafIcon)

Cluster Optionen für Marker

leaflet(quakes) %>% addTiles() %>% addMarkers(
  clusterOptions = markerClusterOptions()
)

Ein Rechteck hinzufügen

leaflet() %>% addTiles() %>%
  addRectangles(
    lng1=-118.456554, lat1=34.078039,
    lng2=-118.436383, lat2=34.062717,
    fillColor = "transparent"
  )

Aufgabe leaflet

Interaktive Tabellen mit DataTables

The R-package DT

install.packages('DT')
library('DT')
exdat <- read.csv("data/exdat.csv")
datatable(exdat)

Beispiel für interaktive Tabelle

Hier ist das Ergebnis - Beispiel für eine interaktive Tabelle

Default Optionen verändern

datatable(head(exdat, 20), options = list(
  columnDefs = list(list(className = 'dt-center', targets = 5)),
  pageLength = 5,
  lengthMenu = c(5, 10, 15, 20)
))

Suchoptionen kennzeichnen

datatable(exdat, options = list(searchHighlight = TRUE), filter = 'top')

R und die Javascript Data-Driven Documents (D3)

JavaScript - Data-Driven Documents

gigvis

install.packages("ggvis")
library("ggvis")
library(dplyr)

Kochbuch für ggvis

mtcars %>% ggvis(~wt, ~mpg) %>% layer_points()

Plots mit Gruppierung

mtcars %>% 
  ggvis(~wt, ~mpg, fill = ~factor(cyl)) %>% 
  layer_points() %>% 
  group_by(cyl) %>% 
  layer_model_predictions(model = "lm")

Interaktive Graphiken mit ggvis

mtcars %>%
  ggvis(~wt, ~mpg) %>%
  layer_smooths(span = input_slider(0.5, 1, value = 1)) %>%
  layer_points(size := input_slider(100, 1000, value = 100))

googleVis

install.packages("googleVis")
library(googleVis)
df <- data.frame(year=1:11, x=1:11,
                 x.scope=c(rep(TRUE, 8), rep(FALSE, 3)),
                 y=11:1, y.html.tooltip=LETTERS[11:1],                 
                 y.certainty=c(rep(TRUE, 5), rep(FALSE, 6)),
                 y.emphasis=c(rep(FALSE, 4), rep(TRUE, 7)))
plot(
  gvisScatterChart(df,options=list(lineWidth=2))
)

Click me

install.packages("devtools")
library(devtools)

install_github("clickme", "nachocab")
library(clickme)

# simple
clickme("points", 1:10)

# fancy
n <- 500
clickme("points",
    x = rbeta(n, 1, 10), y = rbeta(n, 1, 10),
    names = sample(letters, n, r = T),
    color_groups = sample(LETTERS[1:3], n, r = T),
    title = "Zoom Search Hover Click")

d3Network

install.packages("d3Network")
library(d3Network)
Source <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
Target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
NetworkData <- data.frame(Source, Target)
d3SimpleNetwork(NetworkData, width = 400, height = 250)
## 
##         <!DOCTYPE html>
##         <meta charset="utf-8">
##         <body> 
##  <style>
## .link {
## stroke: #666;
## opacity: 0.6;
## stroke-width: 1.5px;
## }
## .node circle {
## stroke: #fff;
## opacity: 0.6;
## stroke-width: 1.5px;
## }
## text {
## font: 7px serif;
## opacity: 0.6;
## pointer-events: none;
## }
## </style>
## 
## <script src=http://d3js.org/d3.v3.min.js></script>
## 
## <script> 
##  var links = [ { "source" : "A", "target" : "B" }, { "source" : "A", "target" : "C" }, { "source" : "A", "target" : "D" }, { "source" : "A", "target" : "J" }, { "source" : "B", "target" : "E" }, { "source" : "B", "target" : "F" }, { "source" : "C", "target" : "G" }, { "source" : "C", "target" : "H" }, { "source" : "D", "target" : "I" } ] ; 
##  var nodes = {}
## 
## // Compute the distinct nodes from the links.
## links.forEach(function(link) {
## link.source = nodes[link.source] ||
## (nodes[link.source] = {name: link.source});
## link.target = nodes[link.target] ||
## (nodes[link.target] = {name: link.target});
## link.value = +link.value;
## });
## 
## var width = 400
## height = 250;
## 
## var force = d3.layout.force()
## .nodes(d3.values(nodes))
## .links(links)
## .size([width, height])
## .linkDistance(50)
## .charge(-200)
## .on("tick", tick)
## .start();
## 
## var svg = d3.select("body").append("svg")
## .attr("width", width)
## .attr("height", height);
## 
## var link = svg.selectAll(".link")
## .data(force.links())
## .enter().append("line")
## .attr("class", "link");
## 
## var node = svg.selectAll(".node")
## .data(force.nodes())
## .enter().append("g")
## .attr("class", "node")
## .on("mouseover", mouseover)
## .on("mouseout", mouseout)
## .on("click", click)
## .on("dblclick", dblclick)
## .call(force.drag);
## 
## node.append("circle")
## .attr("r", 8)
## .style("fill", "#3182bd");
## 
## node.append("text")
## .attr("x", 12)
## .attr("dy", ".35em")
## .style("fill", "#3182bd")
## .text(function(d) { return d.name; });
## 
## function tick() {
## link
## .attr("x1", function(d) { return d.source.x; })
## .attr("y1", function(d) { return d.source.y; })
## .attr("x2", function(d) { return d.target.x; })
## .attr("y2", function(d) { return d.target.y; });
## 
## node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
## }
## 
## function mouseover() {
## d3.select(this).select("circle").transition()
## .duration(750)
## .attr("r", 16);
## }
## 
## function mouseout() {
## d3.select(this).select("circle").transition()
## .duration(750)
## .attr("r", 8);
## }
## // action to take on mouse click
## function click() {
## d3.select(this).select("text").transition()
## .duration(750)
## .attr("x", 22)
## .style("stroke-width", ".5px")
## .style("opacity", 1)
## .style("fill", "#E34A33")
## .style("font", "17.5px serif");
## d3.select(this).select("circle").transition()
## .duration(750)
## .style("fill", "#E34A33")
## .attr("r", 16)
## }
## 
## // action to take on mouse double click
## function dblclick() {
## d3.select(this).select("circle").transition()
## .duration(750)
## .attr("r", 6)
## .style("fill", "#E34A33");
## d3.select(this).select("text").transition()
## .duration(750)
## .attr("x", 12)
## .style("stroke", "none")
## .style("fill", "#E34A33")
## .style("stroke", "none")
## .style("opacity", 0.6)
## .style("font", "7px serif");
## }
## 
## </script>
##  </body>
sink("FirstNetwork.js") 

writeLines(d3SimpleNetwork(NetworkData), fileConn)
unlink("FirstNetwork.js")

HTML widgets in R

library(dygraphs)
dygraph(nhtemp, main = "New Haven Temperatures") %>% 
  dyRangeSelector(dateWindow = c("1920-01-01", "1960-01-01"))

Combo Chart

library(googleVis)
op <- options(gvis.plot.tag = "chart")
## Add the mean
CityPopularity$Mean=mean(CityPopularity$Popularity)
CC <- gvisComboChart(CityPopularity, xvar='City',
          yvar=c('Mean', 'Popularity'),
          options=list(seriesType='bars',
                       width=450, height=300,
                       title='City Popularity',
                       series='{0: {type:\"line\"}}'))
plot(CC)
## <!-- ComboChart generated in R 3.3.3 by googleVis 0.6.2 package -->
## <!-- Sat May 06 22:18:19 2017 -->
## 
## 
## <!-- jsHeader -->
## <script type="text/javascript">
##  
## // jsData 
## function gvisDataComboChartID10b81f505666 () {
## var data = new google.visualization.DataTable();
## var datajson =
## [
##  [
## "New York",
## 450,
## 200
## ],
## [
## "Boston",
## 450,
## 300
## ],
## [
## "Miami",
## 450,
## 400
## ],
## [
## "Chicago",
## 450,
## 500
## ],
## [
## "Los Angeles",
## 450,
## 600
## ],
## [
## "Houston",
## 450,
## 700
## ] 
## ];
## data.addColumn('string','City');
## data.addColumn('number','Mean');
## data.addColumn('number','Popularity');
## data.addRows(datajson);
## return(data);
## }
##  
## // jsDrawChart
## function drawChartComboChartID10b81f505666() {
## var data = gvisDataComboChartID10b81f505666();
## var options = {};
## options["allowHtml"] = true;
## options["seriesType"] = "bars";
## options["width"] = 450;
## options["height"] = 300;
## options["title"] = "City Popularity";
## options["series"] = {0: {type:"line"}};
## 
## 
##     var chart = new google.visualization.ComboChart(
##     document.getElementById('ComboChartID10b81f505666')
##     );
##     chart.draw(data,options);
##     
## 
## }
##   
##  
## // jsDisplayChart
## (function() {
## var pkgs = window.__gvisPackages = window.__gvisPackages || [];
## var callbacks = window.__gvisCallbacks = window.__gvisCallbacks || [];
## var chartid = "corechart";
##   
## // Manually see if chartid is in pkgs (not all browsers support Array.indexOf)
## var i, newPackage = true;
## for (i = 0; newPackage && i < pkgs.length; i++) {
## if (pkgs[i] === chartid)
## newPackage = false;
## }
## if (newPackage)
##   pkgs.push(chartid);
##   
## // Add the drawChart function to the global list of callbacks
## callbacks.push(drawChartComboChartID10b81f505666);
## })();
## function displayChartComboChartID10b81f505666() {
##   var pkgs = window.__gvisPackages = window.__gvisPackages || [];
##   var callbacks = window.__gvisCallbacks = window.__gvisCallbacks || [];
##   window.clearTimeout(window.__gvisLoad);
##   // The timeout is set to 100 because otherwise the container div we are
##   // targeting might not be part of the document yet
##   window.__gvisLoad = setTimeout(function() {
##   var pkgCount = pkgs.length;
##   google.load("visualization", "1", { packages:pkgs, callback: function() {
##   if (pkgCount != pkgs.length) {
##   // Race condition where another setTimeout call snuck in after us; if
##   // that call added a package, we must not shift its callback
##   return;
## }
## while (callbacks.length > 0)
## callbacks.shift()();
## } });
## }, 100);
## }
##  
## // jsFooter
## </script>
##  
## <!-- jsChart -->  
## <script type="text/javascript" src="https://www.google.com/jsapi?callback=displayChartComboChartID10b81f505666"></script>
##  
## <!-- divChart -->
##   
## <div id="ComboChartID10b81f505666" 
##   style="width: 450; height: 300;">
## </div>
install.packages("threejs")
# install.packages("threejs")
library(threejs)
z <- seq(-10, 10, 0.01)
x <- cos(z)
y <- sin(z)
scatterplot3js(x,y,z, color=rainbow(length(z)))

Interaktive Graphiken mit D3 und plotly

plotly Installieren

install.packages("plotly")
library("plotly")

Der Anfang mit plotly für R

p <- plot_ly(midwest, x = ~percollege, color = ~state, type = "box")
p

plotly Beispiel mit eigenen Daten

url <- "https://raw.githubusercontent.com/Japhilko/GeoData/master/2015/data/whcSites.csv"

whcSites <- read.csv(url) 
p <- plot_ly(whcSites, x = ~date_inscribed, color = ~category_short, type = "box")
p

Netzwerkgraphiken mit vis.js

Introduction to visNetwork

# install.packages("visNetwork")
library(visNetwork)

Ein Minimalbeispiel

nodes <- data.frame(id = 1:3)
edges <- data.frame(from = c(1,2), to = c(1,3))
visNetwork(nodes, edges, width = "100%")

Wie es funktioniert

visDocumentation()
vignette("Introduction-to-visNetwork") # with CRAN version

Shiny Beispiel

shiny::runApp(system.file("shiny", package = "visNetwork"))

d3-Netzwerkgraphiken mit R

Das Erstellen von Ablaufdiagrammen mit mermaid

Um was geht es?

install.packages('DiagrammeR')
library('DiagrammeR')

Creating a simple graph

DiagrammeR("
  graph LR
    A-->B
    A-->C
    C-->E
    B-->D
    C-->D
    D-->F
    E-->F
")

Creating a GANTT diagramm

DiagrammeR("
gantt
        dateFormat  YYYY-MM-DD
        title Adding GANTT diagram functionality to mermaid
        section A section
        Completed task            :done,    des1, 2014-01-06,2014-01-08
        Active task               :active,  des2, 2014-01-09, 3d
        Future task               :         des3, after des2, 5d
        Future task2               :         des4, after des3, 5d
        section Critical tasks
        Completed task in the critical line :crit, done, 2014-01-06,24h
        Implement parser and jison          :crit, done, after des1, 2d
        Create tests for parser             :crit, active, 3d
        Future task in critical line        :crit, 5d
        Create tests for renderer           :2d
        Add to mermaid                      :1d
")

Ein weiteres Gantt Diagramm

library(DiagrammeR)
mermaid("
gantt
dateFormat  YYYY-MM-DD
title A Very Nice Gantt Diagram

section Basic Tasks
This is completed             :done,          first_1,    2014-01-06, 2014-01-08
This is active                :active,        first_2,    2014-01-09, 3d
Do this later                 :               first_3,    after first_2, 5d
Do this after that            :               first_4,    after first_3, 5d

section Important Things
Completed, critical task      :crit, done,    import_1,   2014-01-06,24h
Also done, also critical      :crit, done,    import_2,   after import_1, 2d
Doing this important task now :crit, active,  import_3,   after import_2, 3d
Next critical task            :crit,          import_4,   after import_3, 5d

section The Extras
First extras                  :active,        extras_1,   after import_4,  3d
Second helping                :               extras_2,   after extras_1, 20h
More of the extras            :               extras_3,   after extras_1, 48h
")

Addins für RStudio

Rstudio AddIns

Ein AddIn um Farben auszuwählen

install.packages("shinyjs")

Das Paket shinyjs

citation("shinyjs")
## 
## To cite package 'shinyjs' in publications use:
## 
##   Dean Attali (2016). shinyjs: Easily Improve the User Experience
##   of Your Shiny Apps in Seconds. R package version 0.9.
##   https://CRAN.R-project.org/package=shinyjs
## 
## A BibTeX entry for LaTeX users is
## 
##   @Manual{,
##     title = {shinyjs: Easily Improve the User Experience of Your Shiny Apps in Seconds},
##     author = {Dean Attali},
##     year = {2016},
##     note = {R package version 0.9},
##     url = {https://CRAN.R-project.org/package=shinyjs},
##   }